package ch.nostromo.tiffanys.engines.tiffanys.ai;

import java.util.*;

import ch.nostromo.tiffanys.engines.tiffanys.board.TiffanysBoard;
import ch.nostromo.tiffanys.game.board.Board;
import ch.nostromo.tiffanys.game.game.Game;

/**
 * This class implements the computation of a Zobrist key.
 */
public class ZobristKeyImpl {

  // Static variables

  /**
   * The random numbers for the key computation.
   */
  private static long[][][] _factors;

  /**
   * The factor for black moves.
   */
  private static long _blackMoves;

  // Instance variables

  // Constructors

  /**
   * Create a new key instance.
   */
  static {

    // Create a new multidimensional array.
    _factors = new long[2][6][64];

    Random rand = new Random();

    for (int i = 0; i < 64; i++) {
      for (int j = 0; j < 6; j++) {
        _factors[0][j][i] = rand.nextLong();
        _factors[1][j][i] = rand.nextLong();
      }
    }

    _blackMoves = rand.nextLong();
  }

  // Methods

  /**
   * Compute a key for a board and a color.
   * 
   * @param board
   *          The current board.
   * @param white
   *          Flag to indicate if white moves.
   * 
   * @return The zobrist key.
   */
  public static long computeKey(long[] board, int colorToMove) {

    long val = 0L;

    for (int i = 0; i < TiffanysBoard.BOARD64.length; i++) {
      if ((Board.EMPTY_FIELD & board[TiffanysBoard.BOARD64[i]]) == 0) {
        // Get the typ
        // 0 = KING
        int type = 0;
        if ((Board.PIECE_PAWN & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 1;
        } else if ((Board.PIECE_KNIGHT & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 2;
        } else if ((Board.PIECE_BISHOP & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 3;
        } else if ((Board.PIECE_ROOK & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 4;
        } else if ((Board.PIECE_QUEEN & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 5;
        }

        // get the color
        int col = 0;
        if ((Board.OWNER_BLACK & board[TiffanysBoard.BOARD64[i]]) != 0) {
          col = 1;
        }

        val ^= _factors[col][type][i];

      }
    }

    if (Game.COLOR_BLACK == colorToMove) {
      val ^= _blackMoves;
    }

    return val;

  }
  
  public static long computeKeyOld(int[] board, int colorToMove) {

    long val = 0L;

    for (int i = 0; i < TiffanysBoard.BOARD64.length; i++) {
      if ((Board.EMPTY_FIELD & board[TiffanysBoard.BOARD64[i]]) == 0) {
        // Get the typ
        // 0 = KING
        int type = 0;
        if ((Board.PIECE_PAWN & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 1;
        } else if ((Board.PIECE_KNIGHT & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 2;
        } else if ((Board.PIECE_BISHOP & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 3;
        } else if ((Board.PIECE_ROOK & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 4;
        } else if ((Board.PIECE_QUEEN & board[TiffanysBoard.BOARD64[i]]) != 0) {
          type = 5;
        }

        // get the color
        int col = 0;
        if ((Board.OWNER_BLACK & board[TiffanysBoard.BOARD64[i]]) != 0) {
          col = 1;
        }

        val ^= _factors[col][type][i];

      }
    }

    if (Game.COLOR_BLACK == colorToMove) {
      val ^= _blackMoves;
    }

    return val;

  }
  
  
}
